package cn.joyfulmedia.common.util;

import com.alibaba.fastjson.JSON;
import cn.joyfulmedia.common.dto.APIException;
import cn.joyfulmedia.common.dto.BaseResponse;
import cn.joyfulmedia.common.dto.ResultDO;
import cn.joyfulmedia.common.log.CustomLogger;
import cn.joyfulmedia.common.result.CommonResultCodeEnum;
import cn.joyfulmedia.common.result.ModuleResultCode;
import cn.joyfulmedia.common.result.ResultCodeInterface;
import org.springframework.jdbc.BadSqlGrammarException;
import redis.clients.jedis.exceptions.JedisException;

import java.io.IOException;
import java.sql.SQLException;
import java.util.concurrent.TimeoutException;

/**
 * 日志工具类
 * <p>
 * info(1000000, "参数异常", "传入参数a为:{},b为:{}", "aaaa", "bbbb")
 * 输出为:[code:1000000] [msg:参数异常] 传入参数a为:aaaa,b为:bbbb
 * <p>
 * 自定义log代码:
 * private static final CustomLogger log = CustomLoggerFactory.getLogger(UserManageServiceImpl.class);
 *
 * @author yujun
 * @create 2016-11-09 18:02
 */
public class LoggerUtils {

    public static void info(CustomLogger log, ResultCodeInterface resultCode) {
        log.customInfo(resultCode.getResultCode(), resultCode.getMessage(), "");
    }

    public static void info(CustomLogger log, int code, String msg) {
        log.customInfo(code, msg, "");
    }

    /**
     * customInfo(1000000, "参数异常", "传入参数a为:{},b为:{}", "aaaa", "bbbb")
     * 输出为:[code:1000000] [msg:参数异常] 传入参数a为:aaaa,b为:bbbb
     *
     * @param log        自定义log,包含发生异常信息类等信息
     * @param resultCode code and msg
     * @param format     其余信息模板
     * @param arguments  其他参数
     */
    public static void info(CustomLogger log, ResultCodeInterface resultCode, String format, Object... arguments) {
        log.customInfo(resultCode.getResultCode(), resultCode.getMessage(), format, arguments);
    }

    public static void info(CustomLogger log, int code, String msg, String format, Object... arguments) {
        log.customInfo(code, msg, format, arguments);
    }


    public static void warn(CustomLogger log, ResultCodeInterface resultCode) {
        log.customWarn(resultCode.getResultCode(), resultCode.getMessage(), "");
    }

    public static void warn(CustomLogger log, int code, String msg) {
        log.customWarn(code, msg, "");
    }

    public static void warn(CustomLogger log, ResultCodeInterface resultCode, String format, Object... arguments) {
        log.customWarn(resultCode.getResultCode(), resultCode.getMessage(), format, arguments);
    }

    public static void warn(CustomLogger log, int code, String msg, String format, Object... arguments) {
        log.customWarn(code, msg, format, arguments);
    }


    public static void error(CustomLogger log, ResultCodeInterface resultCode) {
        log.customError(resultCode.getResultCode(), resultCode.getMessage(), "");
    }

    public static void error(CustomLogger log, int code, String msg) {
        log.customError(code, msg, "");
    }

    public static void error(CustomLogger log, ResultCodeInterface resultCode, String format, Object... arguments) {
        log.customError(resultCode.getResultCode(), resultCode.getMessage(), format, arguments);
    }

    public static void error(CustomLogger log, int code, String msg, String format, Object... arguments) {
        log.customError(code, msg, format, arguments);
    }

    public static void error(CustomLogger log, int code, String msg, Throwable t, String format, Object... arguments) {
        log.customError(code, msg, t, format, arguments);
    }

    /**
     * 输出自定义异常
     *
     * @param log              自定义log,包含发生异常信息类等信息
     * @param e                异常
     * @param moduleResultCode 模块code信息
     * @param arguments        其他自定义参数
     */
    public static void error(CustomLogger log, Exception e, ModuleResultCode moduleResultCode, Object... arguments) {
        // 自定义异常
        if (e instanceof APIException) {
            log.warn("[code:{}] [msg:{}] {}", ((APIException) e).getResultCode(), ((APIException) e).getErrorMessage(), JSON.toJSON(arguments));
        }
        // 参数校验失败
        else if (e instanceof IllegalArgumentException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.ILLEGAL_ARGUMENT_EXCEPTION.getResultCode();
            final String resultMsg = e.getMessage();
            log.warn("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments));
        }
        // 数据库异常
        else if (e instanceof SQLException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.SQL_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.SQL_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {} {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
        }
        // 连接超时异常
        else if (e instanceof TimeoutException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.TIME_OUT_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.TIME_OUT_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
        }
        // IO异常(比如读取超时)
        else if (e instanceof IOException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.IO_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.IO_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
        }
        // Redis异常
        else if (e instanceof JedisException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.REDIS_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.REDIS_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
        }
        // 其他位置异常
        else {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.UNKNOW_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.UNKNOW_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
        }
    }

    /**
     * 输出自定义异常 + BaseResponse封装
     *
     * @param log              自定义log,包含发生异常信息类等信息
     * @param e                异常
     * @param moduleResultCode 模块code信息
     * @param response         需要返回的BaseResponse
     * @param arguments        其他自定义参数
     */
    public static void errorAndBaseResponse(CustomLogger log, Exception e, ModuleResultCode moduleResultCode, BaseResponse response, Object... arguments) {
        e.printStackTrace();
        // 自定义异常
        if (e instanceof APIException) {
            log.warn("[code:{}] [msg:{}] {}", ((APIException) e).getResultCode(), ((APIException) e).getErrorMessage(), JSON.toJSON(arguments));
            response.setCode(((APIException) e).getResultCode());
            response.setMsg(((APIException) e).getErrorMessage());
        }
        // 参数校验失败
        else if (e instanceof IllegalArgumentException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.ILLEGAL_ARGUMENT_EXCEPTION.getResultCode();
            final String resultMsg = e.getMessage();
            log.warn("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments));
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
        // 数据库异常
        else if (e instanceof SQLException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.SQL_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.SQL_EXCEPTION.getMessage();
            log.error("[code:" + resultCode + "] [msg:" + resultMsg + "] " + JSON.toJSON(arguments), e);
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
        // 连接超时异常
        else if (e instanceof TimeoutException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.TIME_OUT_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.TIME_OUT_EXCEPTION.getMessage();
            log.error("[code:" + resultCode + "] [msg:" + resultMsg + "] " + JSON.toJSON(arguments), e);
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
        // IO异常(比如读取超时)
        else if (e instanceof IOException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.IO_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.IO_EXCEPTION.getMessage();
            log.error("[code:" + resultCode + "] [msg:" + resultMsg + "] " + JSON.toJSON(arguments), e);
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
        // Redis异常
        else if (e instanceof JedisException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.REDIS_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.REDIS_EXCEPTION.getMessage();
            log.error("[code:" + resultCode + "] [msg:" + resultMsg + "] " + JSON.toJSON(arguments), e);
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
        // 其他位置异常
        else {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.UNKNOW_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.UNKNOW_EXCEPTION.getMessage();
            log.error("[code:" + resultCode + "] [msg:" + resultMsg + "] " + JSON.toJSON(arguments), e);
            response.setCode(resultCode);
            response.setMsg(resultMsg);
        }
    }

    /**
     * 输出自定义异常 + ResultDO封装
     *
     * @param log              自定义log,包含发生异常信息类等信息
     * @param e                异常
     * @param moduleResultCode 模块(服务)对应编码
     * @param result           需要返回的ResultDO对象
     */
    public static void errorAndResultDO(CustomLogger log, Exception e, ModuleResultCode moduleResultCode, ResultDO result, Object... arguments) {
        // 自定义异常
        if (e instanceof APIException) {
            log.warn("[code:{}] [msg:{}] {}", ((APIException) e).getResultCode(), ((APIException) e).getErrorMessage(), JSON.toJSON(arguments));
            result.setResultCode(((APIException) e).getResultCode());
            result.setErrorMessage(((APIException) e).getErrorMessage());
        }
        // 参数校验失败
        else if (e instanceof IllegalArgumentException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.ILLEGAL_ARGUMENT_EXCEPTION.getResultCode();
            final String resultMsg = e.getMessage();
            log.warn("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments));
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        // 数据库异常
        else if (e instanceof SQLException || e instanceof BadSqlGrammarException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.SQL_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.SQL_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {} {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        // 连接超时异常
        else if (e instanceof TimeoutException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.TIME_OUT_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.TIME_OUT_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        // IO异常(比如读取超时)
        else if (e instanceof IOException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.IO_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.IO_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        // Redis异常
        else if (e instanceof JedisException) {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.REDIS_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.REDIS_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        // 其他位置异常
        else {
            final int resultCode = moduleResultCode.getCode() + CommonResultCodeEnum.UNKNOW_EXCEPTION.getResultCode();
            final String resultMsg = CommonResultCodeEnum.UNKNOW_EXCEPTION.getMessage();
            log.error("[code:{}] [msg:{}] {}", resultCode, resultMsg, JSON.toJSON(arguments), e);
            result.setResultCode(resultCode);
            result.setErrorMessage(resultMsg);
        }
        result.setErrorType(1);
        result.setSuccess(false);
    }
}
